#include "exchange_gltf.h"
#include "ExchangeIO.h"
#include "topology/TopoBuilder.hpp"
#include "common/system_log.h"
#include "utils/file_util.h"
#include "utils/string_util.h"
#include "ExchangeTopoShape.h"
#include "ExchangeMaterials.h"
AMCAX_EXCHANGE_NAMESPACE_BEGIN

void ExchangeGltf::ReadFromFilePath()
{
    throw std::runtime_error("unsupport");
}

void ExchangeGltf::ReadFromFileStream()
{
    throw std::runtime_error("unsupport");
}

// void ExchangeGltf::Read()
// {
//     throw std::runtime_error("unsupport");
// }

void ExchangeGltf::Write(const std::vector<std::shared_ptr<ExchangeObject>>& exchange_shapes, const std::shared_ptr<ExchangeDocumentInstance> &exchangeDocumentInstance)
{
#ifdef AMCAX_GLTF_ENABLE
    AMCAX::GLTF::AmcaxGltf amcax_gltf;

    GltfOutputParameter *parameter = dynamic_cast<GltfOutputParameter *>(GetExchangeParameter()) ;
    double linearDeflection = DEFAULT_LINEAR_DEFLECTION ;
    double angleDeflection = DEFAULT_ANGLE_DEFLECTION ;
    if (nullptr != parameter) {
        linearDeflection = parameter->GetLinearDeflection();
        linearDeflection = (linearDeflection > MAX_LINEAR_DEFLECTION)? MAX_LINEAR_DEFLECTION : linearDeflection ;
        linearDeflection = (linearDeflection < MIN_LINEAR_DEFLECTION)? MIN_LINEAR_DEFLECTION : linearDeflection ;

        angleDeflection = parameter->GetAngleDeflection();
        angleDeflection = (angleDeflection > MAX_LINEAR_DEFLECTION)? MAX_ANGLE_DEFLECTION : angleDeflection ;
        angleDeflection = (angleDeflection < MIN_LINEAR_DEFLECTION)? MIN_ANGLE_DEFLECTION : angleDeflection ;
    }
    
    int ret = 0 ;
    if (OUTPUT_FILE_TYPE::FILE_PATH == outputFileType_) 
    {
        if (AMCAX::Exchange::file_util::is_file_exist(filePath_))
        {
            LOG_ERROR("file<{}> already exist",filePath_) ;
            return ;
        }
        ret = amcax_gltf.init(filePath_, linearDeflection, angleDeflection,is_glb_);
    }else if(OUTPUT_FILE_TYPE::FILE_OUTPUT_STREAM == outputFileType_)
    {
        if (nullptr == outFileStream_)
        {
            LOG_ERROR("file stream is null") ;
            return ;
        }
        ret = amcax_gltf.init(outFileStream_, linearDeflection, angleDeflection,is_glb_) ;
    }else {
        LOG_ERROR("output file type is unknown") ;
        return ;
    }

    
    if (!ret) 
    {
        LOG_ERROR("filename is incorrect") ;
        return ;
    }

    // NOTE: 将嵌套的exchange object展开后处理
    std::vector<std::shared_ptr<ExchangeObject>> flat_exchange_objects;
    NestedExchangeShapeToFlat(flat_exchange_objects, exchange_shapes) ;

    std::vector<AMCAX::GLTF::GltfShape> gltf_shapes;

    for(auto& exchange_object : flat_exchange_objects) 
    {
        if (exchange_object->shape->GetShape().IsNull()) continue;

        AMCAX::GLTF::GltfShape gltf_shape;
        gltf_shape.name = exchange_object->name;
        gltf_shape.shape = exchange_object->shape->GetShape();

        // 添加默认颜色
        AMCAX::GLTF::GltfMaterialInfo minfo("default");
        minfo.color = AMCAX::GLTF::GltfMaterialColor::createFromHexValue("#d2d2ff");
        gltf_shape.materials[-1] = minfo;

        // 用户配置色
        if (
            exchange_object->materials && 
            !exchange_object->materials->IsEmpty()
        ) 
        {
            // NOTE: 提取shape上的面信息，并根据面信息，将材质信息添加到gltf_shape中
            AMCAX::IndexSet<AMCAX::TopoShape> faces_;
            AMCAX::TopoExplorerTool::MapShapes(exchange_object->shape->GetShape(), AMCAX::ShapeType::Face, faces_);
            for(auto& [sub, mat]: exchange_object->materials->GetMaterials()) {
                if (!faces_.contains(sub))
                {
                    LOG_ERROR("not contains sub:");
                    continue;
                }
                AMCAX::GLTF::GltfMaterialInfo minfo;
                minfo.color = AMCAX::GLTF::GltfMaterialColor::createFromHexValue(mat.GetColor());
                int fid = faces_.index(sub);
                // LOG_DEBUG("test GltfMaterialColor mat.GetColor: {}, fid:{} ", mat.GetColor(), fid);
                if (fid > -1) gltf_shape.materials[fid] = minfo;
            }
        }

        gltf_shapes.push_back(gltf_shape) ;
    }
    
    amcax_gltf.writeShape(gltf_shapes) ;
    amcax_gltf.done() ;
#endif
}


AMCAX_EXCHANGE_NAMESPACE_END